package com.example.questionnaire.mbg.controller;

import com.example.questionnaire.dto.QuestionDTO;
import com.example.questionnaire.dto.QuestionnaireDTO;
import com.example.questionnaire.dto.WantDTO;
import com.example.questionnaire.exception.NotFindException;
import com.example.questionnaire.mbg.comman.R;
import com.example.questionnaire.mbg.entity.Enum.QuestionTypeEnum;
import com.example.questionnaire.mbg.entity.Enum.QuestionnaireStatusEnum;
import com.example.questionnaire.mbg.entity.Enum.QuestionnaireTypeEnum;
import com.example.questionnaire.mbg.entity.Option;
import com.example.questionnaire.mbg.entity.Question;
import com.example.questionnaire.mbg.entity.Questionnaire;
import com.example.questionnaire.mbg.entity.Want;
import com.example.questionnaire.mbg.service.*;
import com.example.questionnaire.validate.QuestionnaireValidate;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;

@RestController
@RequestMapping("/questionnaire")
public class QuestionnaireController {

    @Resource
    private IQuestionnaireService questionnaireService;

    @Resource
    private IUserService userService;

    @Resource
    private IQuestionService questionService;

    @Resource
    private IOptionService optionService;

    @Resource
    private IWantService wantService;

    @PutMapping("/create")
    public R create(@RequestParam("uid") int uid, @RequestBody QuestionnaireDTO dto) {
        if (null == userService.selectUserByID(uid)) {
            return R.fail("uid not exists");
        }
        QuestionnaireValidate.validateTitle(dto.getTitle());

        QuestionnaireValidate.validateType(dto.getType());

        QuestionnaireTypeEnum type = QuestionnaireTypeEnum.fromString(dto.getType());
        List<QuestionDTO> questions = dto.getQuestions();

        String due = null;
        if (dto.getHas_due()) {
            due = dto.getDue();
        }

        int id = new Random().nextInt(1000000000);
        Questionnaire questionnaire = Questionnaire.builder()
                .id(id)
                .questionnaireType(type)
                .showNumber(dto.getShowTag())
                .title(dto.getTitle())
                .created(new Date())
                .description(dto.getDescription())
                .userId(uid)
                .status(QuestionnaireStatusEnum.CREATED)
                .due(due)
                .build();

        questionnaireService.create(questionnaire, questions);
        return R.success(id);
    }

    @GetMapping("/list")
    public R list(@RequestParam int uid, @RequestParam int page, @RequestParam int pageSize) {
        List<Questionnaire> questionnaires = questionnaireService.list(uid, page, pageSize);
        return R.success(questionnaires);
    }

    @GetMapping("/listInTrash")
    public R listInTrash(@RequestParam int uid, @RequestParam int page, @RequestParam int pageSize) {
        List<Questionnaire> questionnaires = questionnaireService.listInTrash(uid, page, pageSize);
        return R.success(questionnaires);
    }

    @PostMapping("/close")
    public R close(@RequestParam int qnid) {
        questionnaireService.close(qnid);
        return R.success("success");
    }

    @PostMapping("/restore")
    public R restore(@RequestParam int qnid) {
        questionnaireService.restore(qnid);
        return R.success("success");
    }

    @PostMapping("/publish")
    public R publish(@RequestParam int qnid) {
        Questionnaire qn = questionnaireService.get(qnid);
        if (null == qn) return R.fail("问卷不存在");
        if (qn.getInTrash()) return R.fail("问卷在回收站");
        if (QuestionnaireStatusEnum.valueOf("PUBLISHED") == qn.getStatus()) return R.fail("问卷已发布");
        questionnaireService.publish(qnid);
        String encodedId = RandomStringUtils.randomAlphanumeric(10);
        while (questionnaireService.exist(encodedId)) {
            encodedId = RandomStringUtils.randomAlphanumeric(10);
        }
        questionnaireService.setEncodedId(qnid, encodedId);
        return R.success(encodedId);
    }

    @DeleteMapping("/remove")
    public R remove(@RequestParam int qnid) {
        Questionnaire qn = questionnaireService.get(qnid);
        questionnaireService.remove(qnid);
        return R.success("success");
    }

    @GetMapping("/fetch")
    public R fetch(@RequestParam("qnid") String encodedId) {
        Questionnaire qn = questionnaireService.getEncoded(encodedId);
        if (null == qn) return R.fail("问卷不存在");
        if (qn.getInTrash()) return R.fail("问卷在回收站");
        if (QuestionnaireStatusEnum.valueOf("PUBLISHED") != qn.getStatus()) return R.fail("问卷不在发布状态");
        return get(qn.getId());
    }

    @GetMapping("/get")
    public R get(@RequestParam("qnid") int qnid) {
        Questionnaire questionnaire = questionnaireService.get(qnid);
        if (null == questionnaire) {
            throw new NotFindException("qnid");
        }

        HashMap<String, Object> rmp = new HashMap<>();
        rmp.put("title", questionnaire.getTitle());
        rmp.put("description", questionnaire.getDescription());
        rmp.put("showTag", questionnaire.getShowNumber());


        rmp.put("type", questionnaire.getQuestionnaireType().toString());
        rmp.put("has_due", null != questionnaire.getDue());
        rmp.put("due", questionnaire.getDue());


        List<Question> questions = questionService.listAll(qnid);
        List<HashMap<String, Object>> submps = new ArrayList<>();
        for (int i = 0; i < questions.size(); i++) {
            submps.add(new HashMap<>());
        }
        for (Question question : questions) {
            int qn = question.getQuestionNumber();
            submps.get(qn).put("title", question.getContent());
            submps.get(qn).put("description", question.getDescription());

            submps.get(qn).put("nullable", question.getNullable());
            submps.get(qn).put("score", question.getScore());
            submps.get(qn).put("hide", question.getHide());
            submps.get(qn).put("interlock_combinator", question.getInterlockCombinator());
            submps.get(qn).put("uuid", question.getUuid());

            List<Want> wants = wantService.listAll(question.getId());

            List<WantDTO> wantDTOS = new ArrayList<>();

            for (Want want : wants) {
                ArrayList<Integer> masks = new ArrayList<>();
                for (String s : want.getMask().split(",")) {
                    masks.add(Integer.valueOf(s));
                }
                WantDTO wantDTO = WantDTO.builder()
                        .inverted(want.getInverted())
                        .mask(masks)
                        .uuid(want.getUuid())
                        .build();
                wantDTOS.add(wantDTO);
            }
            submps.get(qn).put("wants", wantDTOS);

            List<Option> options;
            List<String> ops;
            QuestionTypeEnum qType = question.getQuestionType();

            switch (qType) {
                case LOCATION:
                case INPUT:
                    options = optionService.listAll(question.getId());
                    submps.get(qn).put("text", options.get(0).getContent());
                    submps.get(qn).put("type", qType.toString());
                    submps.get(qn).put("input_answer", options.get(0).getAnswerText());
                    break;
                case CHECKBOX: {
                    options = optionService.listAll(question.getId());
                    ops = new ArrayList<>();
                    ArrayList<Integer> checkbox_answer = new ArrayList<>();
                    ArrayList<Integer> capacity = new ArrayList<>();
                    Boolean has_capacity = false;
                    int idx = 0;
                    for (Option option : options) {
                        ops.add(option.getContent());
                        if (option.getIsRight()) {
                            checkbox_answer.add(idx);
                        }
                        if (option.getCapacity() != 0) {
                            has_capacity = true;
                        }
                        capacity.add(option.getCapacity());
                        idx++;
                    }

                    submps.get(qn).put("choices", ops);
                    submps.get(qn).put("type", qType.toString());
                    submps.get(qn).put("checkbox_answer", checkbox_answer);
                    submps.get(qn).put("capacity", capacity);
                    submps.get(qn).put("has_capacity", has_capacity);

                    break;
                }
                case RADIO:
                    options = optionService.listAll(question.getId());
                    ops = new ArrayList<>();

                    ArrayList<Integer> capacity = new ArrayList<>();
                    Boolean has_capacity = false;
                    int idx = 0;
                    for (Option option : options) {
                        ops.add(option.getContent());
                        if (option.getIsRight()) {
                            submps.get(qn).put("radio_answer", idx);
                        }
                        if (option.getCapacity() != 0) {
                            has_capacity = true;
                        }
                        capacity.add(option.getCapacity());
                        idx++;
                    }
                    submps.get(qn).put("choices", ops);
                    submps.get(qn).put("type", qType.toString());
                    submps.get(qn).put("capacity", capacity);
                    submps.get(qn).put("has_capacity", has_capacity);
                    break;
                case RATING:
                    int n = optionService.getSumByQid(question.getId()) - 1;
                    submps.get(qn).put("number", n);
                    submps.get(qn).put("type", qType.toString());
                    break;
            }
        }
        rmp.put("questions", submps);
        return R.success(rmp);
    }

    @PutMapping("/update")
    public R update(@RequestParam("qnid") int qnid, @RequestBody QuestionnaireDTO dto) {
        if (null == questionnaireService.get(qnid)) {
            throw new NotFindException("qnid");
        }

        QuestionnaireValidate.validateTitle(dto.getTitle());

        QuestionnaireValidate.validateType(dto.getType());

        List<QuestionDTO> questions = dto.getQuestions();

        Questionnaire questionnaire = Questionnaire.builder()
                .id(qnid)
                .showNumber(dto.getShowTag())
                .title(dto.getTitle())
                .description(dto.getDescription())
                .questionnaireType(QuestionnaireTypeEnum.fromString(dto.getType()))
                .build();

        questionnaireService.update(questionnaire, questions);
        return R.success();
    }

    @PutMapping("/alter")
    public R alter(@RequestParam("qnid") int qnid, @RequestBody QuestionnaireDTO dto) {
        if (null == questionnaireService.get(qnid)) {
            return R.fail("qnid not exists");
        }
        String title = dto.getTitle();
        QuestionnaireValidate.validateTitle(title);

        String questionnaireType = dto.getType();
        QuestionnaireValidate.validateType(questionnaireType);

        List<QuestionDTO> questions = dto.getQuestions();


        Questionnaire questionnaire = Questionnaire.builder()
                .id(qnid)
                .showNumber(dto.getShowTag())
                .title(dto.getTitle())
                .description(dto.getDescription())
                .questionnaireType(QuestionnaireTypeEnum.fromString(dto.getType()))
                .build();

        questionnaireService.alter(questionnaire, questions);
        return R.success();
    }

    @GetMapping("/copy")
    public R copy(@RequestParam("qnid") int qnid) {
        Questionnaire qn = questionnaireService.get(qnid);
        qn.setTitle(qn.getTitle() + "_副本");
        return R.success(questionnaireService.copy(qn));
    }
}